package inputs;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import pojo.fromXML.Achievement;
import pojo.fromXML.AchievementRequirement;
import pojo.fromXML.Achievements;
import constants.LocalConstants;
import constants.SystemConstants;
import exception.XMLParsing.MyValidationEventHandler;

/**
 * 
 * @author JohnZantey 
 * <p>
 * The main class to ETL data from TRION for the RIFT game system.
 * </p>
 * <p
 * <p>
 * the XML input must be UTF-8 to allow special characters.
 * </p>
 */
public class xmlReader {
	
	/** 
	 * add logging
	 */
	private static Logger logger = Logger.getLogger("input.xmlReader");
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		readInXMLbyJAXB();
	}

	/**
	 * <p>
	 *   <ul>
	 *     <li>Creates a {@link SchemaFactory SAX Schema Factory} based on <i>xsdFilePath</i></li>
	 *     <li>Qualifies an instantiated {@link JAXBContext JAXB context}</li>
	 *     <li>use {@link Unmarshaller} to get <i>xmlFilePath</i> into {@link achievements Achievements} POJO structure</li>
	 *     <li> Exceptions are {@link Logging logged} as <i>Level.SEVERE</i>:
	 *       <ul>
	 *         <li>{@link SAXException}</li>
	 *         <li>{@link JAXBException}</li>
	 *         <li>{@link FileNotFoundException}</li>
	 *       </ul>
	 *     </li>
	 *   </ul>
	 * </p>
	 * <p>
	 * <p>
	 * <b>TESTING:</b> Iterating through the collection returned is for debugging purposes.
	 * </p>
	 * <p>
	 * The fields retrieved are to serve as examples of obtaining differently structures data
	 * </p>
	 * <b>TODO:</b>This should be a test case.
	 * </p>
	 * <p>
	 * <b>TODO:</b>The reading of data should be performed via delegate factories
	 * or helpers to increase robustness and to modularise and aid mapping
	 * to persistence methods.
	 * </p>
	 */
	private static void readInXMLbyJAXB() {
		try {
			// Create Schema Factory
			SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
	        Schema schema = sf.newSchema(new File(SystemConstants.xsdFilePath)); 			
			
	        // Instantiate JAXB context
			JAXBContext jc = JAXBContext.newInstance(new Class[] { Achievements.class });

			// create and setup un-marshall to parse into object(s)
			Unmarshaller u = jc.createUnmarshaller();
			u.setSchema(schema);
			u.setEventHandler(new MyValidationEventHandler());
			Achievements achievements = (Achievements) u.unmarshal(new FileInputStream(SystemConstants.xmlFilePath));

			// loop through the achievements
			Iterator<Achievement> it = achievements.getAchievement().iterator();
            System.out.println("************************************************************");
			while (it.hasNext()) {
				Achievement achievement = (Achievement) it.next();
				// deal with the unmarshalled object
				System.out.println("Id: " + achievement.getId());
				//
                String categories[] = achievement.getCategory().split(LocalConstants.escapedPeriod);
                if(categories.length > 1) {
                	System.out.println("Category Group: " + categories[0] );
                	System.out.println("Category: " + categories[1] );
                } else {
                	System.out.println("Category: " + achievement.getCategory() );
                }
				//
                System.out.println("Name in English: " + achievement.getName().getEnglish()  + " for " + achievement.getScore().toString() + " points");
                //
                if(achievement.getRewardTitle() != null) {
                	if( achievement.getRewardTitle().getEnglish() != null) {
                		System.out.println("Reward Title in English: " + achievement.getRewardTitle().getEnglish());
                	}
                }
                //
                if(achievement.getRequirements() != null) {
                	if(achievement.getRequirements().getAchievementRequirement().size() > 0) {
                		for(AchievementRequirement achievementRequirement : achievement.getRequirements().getAchievementRequirement() ) {
                			System.out.println("Achievement Requirement Description in English: " + achievementRequirement.getDescription().getEnglish());                			
                		}

                	}
                }
                //
                System.out.println("************************************************************");
			}

		}catch (SAXException se) {
			logger.log(Level.SEVERE, se.getMessage());
		} catch (JAXBException je) {
			logger.log(Level.SEVERE, je.getMessage());
		} catch (FileNotFoundException fnfe) {
			logger.log(Level.SEVERE,  fnfe.getMessage());
		}
	}
}
